package db.dbTables;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;

import core.objects.BaseObject;
import core.objects.enums.GenderEnum;
import core.objects.enums.LoanStatusEnum;
import db.MySQLFormatDate;

public class DbColumn {

    private String name;
    private int type;
    private int size;
    private boolean isNullable;
    private AbstractDBTable parentTable;

    public DbColumn(String name, int type, int size, boolean isNullable, AbstractDBTable parentTable) {
        this.name = name;
        this.type = type;
        this.size = size;
        this.isNullable = isNullable;
        this.parentTable = parentTable;
    }

    public AbstractDBTable getParentTable() {
        return parentTable;
    }

    public boolean isIsNullable() {
        return isNullable;
    }

    public String getName() {
        return parentTable.getName() + "." + name;
    }

    public int getType() {
        return type;
    }

    public int getSize() {
        return size;
    }

    @Override
    public String toString() {
        return name;
    }

    public void setPreparedStatmentArgument(PreparedStatement preSt, int insertIndex, Object objectToInsert) throws SQLException {
        try {
            if (objectToInsert == null) {
                preSt.setNull(insertIndex, type);
            } else {
                switch (type) {
                    case Types.VARCHAR: // Varchar
                        String value = objectToInsert.toString();
                        if (value.length() > size) {
                            value = value.substring(0, size - 1);
                        }
                        preSt.setString(insertIndex, value);
                        break;
                    case Types.DATE: // DATE
                        String date;
                        if (objectToInsert instanceof Date) {
                            date = MySQLFormatDate.toString((Date) objectToInsert);
                        } else {
                            date = MySQLFormatDate.toString((Calendar) objectToInsert);
                        }
                        preSt.setString(insertIndex, date);
                        break;
                    case Types.BIT: // BIT
                        preSt.setBoolean(insertIndex, (Boolean) objectToInsert);
                        break;
                    case Types.TINYINT: //TINYINT (age)
                        preSt.setByte(insertIndex, (byte) objectToInsert);
                        break;
                    case Types.SMALLINT: //SMALLINT (year)
                    case Types.INTEGER: //INT
                        if ((int) objectToInsert == -1) {
                            preSt.setNull(insertIndex, Types.INTEGER);
                        } else if (objectToInsert instanceof BaseObject) {
                            preSt.setInt(insertIndex, ((BaseObject) objectToInsert).getID());
                        } else {
                            preSt.setInt(insertIndex, (int) objectToInsert);
                        }
                        break;
                    case Types.OTHER:
                        if (objectToInsert instanceof GenderEnum || objectToInsert instanceof LoanStatusEnum ) {
                            if (objectToInsert.toString().equals("")){
                                preSt.setNull(insertIndex, type);
                            }
                            else{
                                preSt.setString(insertIndex, objectToInsert.toString());
                            }
                            
                        }
                        break;
                    case Types.TIMESTAMP:
                        if (objectToInsert instanceof Timestamp) {
                            preSt.setTimestamp(insertIndex, (Timestamp) objectToInsert);
                        }
                        break;
                    case Types.BLOB:
                        if (objectToInsert instanceof byte[]) {
                            byte[] imageArr = (byte[]) objectToInsert;
                            InputStream imageStream = new ByteArrayInputStream(imageArr);
                            try {
                                preSt.setBlob(insertIndex, imageStream, imageStream.available());
                            } catch (IOException ex) {
                                Logger.getLogger(DbColumn.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                        break;
                    default:
                        preSt.setNull(insertIndex, type);

                }
            }

        } catch (SQLException | ClassCastException e) {
            System.err.println("Error while setting object " + objectToInsert + " to column " + name + ".");
            e.printStackTrace();
            throw e;
        }
    }
}
